#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "scan.h"
#include "smart_config.h"
#include "esp_log.h"
#include "esp_wpa.h"
#include "esp_wifi.h"
#include "esp_wpa2.h"
#include "string.h"
#include "mywifi.h"

#define TAG "my_wifi"
#define WIFI_SMART_CONFIG_START 0x01
#define WIFI_SCAN_START         0x02
#define WIFI_SCAN_STOP          0x04


static EventGroupHandle_t wifiEvent = NULL;


static void (*connect)();
static void (*disconnect)();
static void (*sc_ok)();
static void (*sc_fail)();
static void (*scan_done)(char *ssid);
static bool isConnected = false;
static bool isSmartConfig = false;
static bool isScan = false;
static void connected_event_handler(void *arg, esp_event_base_t event_base,
                          int32_t event_id, void *event_data)
{

    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
    {
        isConnected = false;
        ESP_LOGI(TAG, "WiFi Disconnected");
    }
    else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
    {
        isConnected = true;
        ESP_LOGI(TAG, "WiFi Connected to ap");
    }
}

static void event_handler(void *arg, esp_event_base_t event_base,
                          int32_t event_id, void *event_data)
{

    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
    {
        if (disconnect)
        {
            disconnect();
        }
        esp_wifi_connect();
    }
    else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
    {
        // // 设置DNS
        // tcpip_adapter_dns_info_t dns_info = {0};
        // IP4_ADDR(&(dns_info.ip.u_addr.ip4), 114, 114, 114, 114);
        // ESP_ERROR_CHECK(tcpip_adapter_set_dns_info(TCPIP_ADAPTER_IF_STA, ESP_NETIF_DNS_MAIN, &dns_info));
        if (connect)
        {
            connect();
        }
    }
}


void my_wifi_task(void *pvParameters)
{
    while (1)
    {
        EventBits_t eventRet = xEventGroupWaitBits(wifiEvent, 0xffff, pdTRUE, pdFALSE, portMAX_DELAY);
        if (eventRet & WIFI_SMART_CONFIG_START)
        {
            isSmartConfig = true;
            ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler));
            ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler));
            smartconfig_wifi();
            ESP_LOGI(TAG, "smartconfig_wifi");
            if (wait_smart_config(600000 / portTICK_PERIOD_MS) == 0)// 10分钟没有配网成功就退出配网
            {
                if (sc_fail)
                {
                    sc_fail();
                    sc_stop();
                }
                ESP_LOGI(TAG, "smartconfig_wifi fail");
            }
            else
            {
                if (sc_ok)
                {
                    sc_ok();
                }
                ESP_LOGI(TAG, "smartconfig_wifi success");
            }
            xEventGroupClearBits(wifiEvent, WIFI_SMART_CONFIG_START); // 防止后面重新进入，提前清空
            ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
            ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
        }
        isSmartConfig = false;
        if (eventRet & WIFI_SCAN_START)
        {
            isScan = true;
            wifi_scan(scan_done);
        }
        if (eventRet & WIFI_SCAN_STOP)
        {
            wifi_scan_stop();
            isScan = false;
        }
    }
}


esp_netif_t *sta_netif;
void my_wifi_init()
{
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    // wifi_config_t wifi_config =
    // {
    //     .sta = {
    //         .ssid = "miio_default",
    //         .password = "123456789",
    //     },
    // };
    // esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
    ESP_ERROR_CHECK(esp_wifi_start());
    esp_wifi_connect();
    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &connected_event_handler, NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &connected_event_handler, NULL));
    
    wifiEvent = xEventGroupCreate();

    xTaskCreate(my_wifi_task, "my_wifi_task", 2048, NULL, 9, NULL);
}

/**
 * @brief 启动配网
 *
 * @param ok 配网成功回调
 * @param fail 配网失败回调
 */
void my_wifi_start_smartconfig(void(*ok)(), void(*fail)())
{
    sc_ok = ok;
    sc_fail = fail;
    xEventGroupSetBits(wifiEvent, WIFI_SMART_CONFIG_START);
}

/**
 * @brief 强制关闭配网
 *
 */
void my_wifi_stop_smartconfig()
{
    smart_config_end();
}

/**
 * @brief 设置连接成功回调
 *
 * @param cb
 */
void my_wifi_set_connect_cb(void(*cb)())
{
    connect = cb;
}

/**
 * @brief 设置连接失败回调
 *
 * @param cb
 */
void my_wifi_set_disconnect_cb(void(*cb)())
{
    disconnect = cb;
}


int my_wifi_is_connected()
{
    return isConnected;
}

wifi_config_t wifi_config;

char *my_wifi_ssid_now()
{
    if (esp_wifi_get_config(ESP_IF_WIFI_STA, &wifi_config) == ESP_OK)
    {
        ESP_LOGI(TAG, "ssid:%s", wifi_config.sta.ssid);
        return (char *)wifi_config.sta.ssid;
    }
    return NULL;
}

void my_wifi_start_scan(void (*scan_done_cb)(char *ssid))
{
    scan_done = scan_done_cb;
    xEventGroupSetBits(wifiEvent, WIFI_SCAN_START);
}

void my_wifi_stop_scan()
{
    xEventGroupSetBits(wifiEvent, WIFI_SCAN_STOP);
}

void my_wifi_connect(char *ssid, char *pwd)
{
    ESP_LOGI(TAG,"connet disconnect");
    esp_wifi_disconnect();
    esp_wifi_stop();
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    wifi_config_t wifi_config = {0};

    strcpy((char *)wifi_config.sta.ssid, ssid);
    strcpy((char *)wifi_config.sta.password, pwd);
    esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
    ESP_ERROR_CHECK(esp_wifi_start());
    esp_wifi_connect();
}

char *my_wifi_get_scan_result(int i)
{
    return wifi_get_scan_result(i);
}
